/*

 * Copyright (C) 2021 Huawei Device Co., Ltd.

 * Licensed under the Apache License, Version 2.0 (the "License");

 * you may not use this file except in compliance with the License.

 * You may obtain a copy of the License at

 *

 *     http://www.apache.org/licenses/LICENSE-2.0

 *

 * Unless required by applicable law or agreed to in writing, software

 * distributed under the License is distributed on an "AS IS" BASIS,

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

 * See the License for the specific language governing permissions and

 * limitations under the License.

 */
package com.ubhave.sensormanager.ability;

import com.ubhave.sensormanager.*;
import com.ubhave.sensormanager.bean.LocationBean;
import com.ubhave.sensormanager.data.SensorData;
import com.ubhave.sensormanager.data.pull.LocationData;
import com.ubhave.sensormanager.provider.LocationItemProvider;
import com.ubhave.sensormanager.sensors.SensorUtils;
import com.ubhave.sensormanager.utils.LogUtil;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Component;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.ToastDialog;
import ohos.bundle.IBundleManager;
import ohos.event.commonevent.*;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.location.Location;
import ohos.location.Locator;
import ohos.rpc.RemoteException;
import ohos.telephony.CellularDataInfoManager;
import ohos.utils.PacMap;
import ohos.utils.Sequenceable;
import ohos.wifi.WifiDevice;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

public class LocationAbility extends Ability implements SensorDataListener, Component.ClickedListener {

    private int subscriptionId;
    private ESSensorManager sensorManager;
    private Text text_data;
    private ListContainer locationList;
    private LocationItemProvider locationItemProvider;
    private CommonEventSubscriber broadcastReceiver;
    private String[] permission = new String[]{"ohos.permission.LOCATION", "ohos.permission.LOCATION_IN_BACKGROUND"};
    private ArrayList<Sequenceable> locations = new ArrayList<>();
    private CellularDataInfoManager cellularDataInfoManager;
    private Locator locator;
    private WifiDevice wifiDevice;
    private EventHandler handler = new EventHandler(EventRunner.getMainEventRunner());

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_location);
        text_data = (Text) findComponentById(ResourceTable.Id_data_location);
        findComponentById(ResourceTable.Id_start_btn).setClickedListener(this::onClick);
        findComponentById(ResourceTable.Id_stop_btn).setClickedListener(this::onClick);

        cellularDataInfoManager = CellularDataInfoManager.getInstance(getContext());
        wifiDevice = WifiDevice.getInstance(getContext());
        locator = new Locator(getContext());

        locationList = (ListContainer) findComponentById(ResourceTable.Id_locationList);
        locationItemProvider = new LocationItemProvider(locations, this);
        locationList.setItemProvider(locationItemProvider);
        locationList.setItemClickedListener((listContainer, component, position, id) -> {
            LocationBean item = (LocationBean) listContainer.getItemProvider().getItem(position);
            new ToastDialog(getContext())
                    .setText("clicked:" + item.getLatitude() + "," + item.getLongitude())
                    .setAlignment(LayoutAlignment.CENTER)
                    .show();
        });
        requestPermissions();
        registeBroadCast();
    }

    private void registeBroadCast() {

        /*MatchingSkills skills = new MatchingSkills();
        skills.addEvent("default.Location");
        CommonEventSubscribeInfo subscribeInfo = new CommonEventSubscribeInfo(skills);
        broadcastReceiver = new CommonEventSubscriber(subscribeInfo) {
            @Override
            public void onReceiveEvent(CommonEventData commonEventData) {

                final Intent intent = commonEventData.getIntent();
                final IntentParams params = intent.getParams();
                getContext().getUITaskDispatcher().asyncDispatch(new Runnable() {
                    @Override
                    public void run() {
                        final Boolean hasData = (Boolean) params.getParam("hasData");
                        if (hasData) {
                            final Double latitude = (Double) params.getParam("latitude");
                            final Double longitude = (Double) params.getParam("longitude");
                            final Float accuracy = (Float) params.getParam("accuracy");
                            final Double direction = (Double) params.getParam("direction");
                            final Float speed = (Float) params.getParam("speed");
                            final Long timeMillis = (Long) params.getParam("timeMillis");
                            LocationBean location = new LocationBean(latitude, longitude);
                            location.setAccuracy(accuracy);
                            location.setDirection(direction);
                            location.setSpeed(speed);
                            location.setTimeMillis(timeMillis);
                            locations.add(location);
                            locationItemProvider.notifyDataChanged();

                            Date date = new Date();
                            date.setTime(timeMillis);
                            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                            String dateString = dateFormat.format(date);

                            StringBuffer buffer = new StringBuffer();
                            buffer.append("数据").append("\n");
                            buffer.append("senseStartTime: " + timeMillis).append("\n");
                            buffer.append("senseStartTimeMillis: " + dateString);
                            text_data.setText(buffer.toString());
                        } else {
                            text_data.setText("暂无定位数据");
                        }

                    }
                });
            }
        };
        try {
            CommonEventManager.subscribeCommonEvent(broadcastReceiver);
        } catch (RemoteException e) {
            e.printStackTrace();
        }*/
    }

    private void requestPermissions() {
        for (String s : permission) {
            if (verifySelfPermission(s) != IBundleManager.PERMISSION_GRANTED) {
                // 应用未被授予权限
                if (canRequestPermission(s)) {
                    // 是否可以申请弹框授权(首次申请或者用户未选择禁止且不再提示)
                    requestPermissionsFromUser(permission, 1001);
                } else {
                    // 显示应用需要权限的理由，提示用户进入设置授权
                }
            } else {
                // 权限已被授予
                System.out.println("已授权");
            }
        }
    }

    @Override
    public void onRequestPermissionsFromUserResult(int requestCode, String[] permissions, int[] grantResults) {
        switch (requestCode) {
            case 1001: {
                // 匹配requestPermissions的requestCode
                if (grantResults.length > 0
                        && grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
                    // 权限被授予
                    // 注意：因时间差导致接口权限检查时有无权限，所以对那些因无权限而抛异常的接口进行异常捕获处理
                    System.out.println("已授权");
                } else {
                    // 权限被拒绝
                }
                break;
            }
        }
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (sensorManager != null) {
            try {
                sensorManager.unsubscribeFromSensorData(subscriptionId);
//                CommonEventManager.unsubscribeCommonEvent(broadcastReceiver);
            } catch (ESException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onClick(Component component) {
        switch (component.getId()) {
            case ResourceTable.Id_start_btn:
                LogUtil.loge("===Id_start_btn");
                try {
                    if (netAndLocationEnable()) {
                        locations.clear();
                        text_data.setText("数据获取中,请耐心等待");
                        sensorManager = ESSensorManager.getSensorManager(getContext());
                        subscriptionId = sensorManager.subscribeToSensorData(SensorUtils.SENSOR_TYPE_LOCATION, this);
                    } else {
                        text_data.setText("请连接网络并打开位置信息后点击开始");
                    }

                } catch (ESException e) {
                    e.printStackTrace();
                }
                break;
            case ResourceTable.Id_stop_btn:
                LogUtil.loge("===Id_stop_btn");
                if (sensorManager != null) {
                    try {
                        text_data.setText("停止操作");
                        sensorManager.unsubscribeFromSensorData(subscriptionId);
                    } catch (ESException e) {
                        e.printStackTrace();
                    }
                }
                break;
        }
    }

    private boolean netAndLocationEnable() {
        if ((cellularDataInfoManager.isCellularDataEnabled() || wifiDevice.isConnected()) && locator.isLocationSwitchOn()) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public void onDataSensed(SensorData data) {
        LogUtil.loge("===onDataSensed: " + data.toString());
        if (!(data instanceof LocationData)) {
            return;
        }
        LocationData locationData = (LocationData) data;
        List<Location> locations = locationData.getLocations();

        if (locations.size() > 0) {
            handler.postTask(() -> {
                long timeMillis = 0;
                for (int i = 0; i < locations.size(); i++) {
                    Location location = locations.get(i);

                    LocationBean locationBean = new LocationBean(location.getLatitude(), location.getLongitude());
                    locationBean.setAccuracy(location.getAccuracy());
                    locationBean.setDirection(location.getDirection());
                    locationBean.setSpeed(location.getSpeed());
                    timeMillis = location.getTimeStamp();
                    locationBean.setTimeMillis(timeMillis);
                    this.locations.add(locationBean);
                }
                locationItemProvider.notifyDataChanged();

                Date date = new Date();
                date.setTime(timeMillis);
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                String dateString = dateFormat.format(date);

                StringBuffer buffer = new StringBuffer();
                buffer.append("数据").append("\n");
                buffer.append("senseStartTime: " + timeMillis).append("\n");
                buffer.append("senseStartTimeMillis: " + dateString);
                text_data.setText(buffer.toString());
            });
        } else {
            handler.postTask(() -> {
                text_data.setText("暂无定位数据");
            });
        }
    }

    @Override
    public void onCrossingLowBatteryThreshold(boolean isBelowThreshold) {
        LogUtil.loge("===onCrossingLowBatteryThreshold: " + isBelowThreshold);
    }

    @Override
    public void onRestoreAbilityState(PacMap inState) {
        super.onRestoreAbilityState(inState);
        ArrayList<Sequenceable> sequenceable = inState.getSequenceableList("sensorData");
        locations.clear();
        locations.addAll(sequenceable);
        locationItemProvider.notifyDataChanged();
    }

    @Override
    public void onSaveAbilityState(PacMap outState) {
        super.onSaveAbilityState(outState);
        if (locationList != null) {
            outState.putSequenceableObjectList("sensorData", locations);
        }
    }

}